package com.hwy.chart.coordinate.axis

import android.graphics.Canvas
import android.graphics.RectF
import com.hwy.chart.component.BaseComponent
import kotlin.math.max
import kotlin.math.min

/**
 * =======================================
 * 作者: hewenyu
 * 日期: 2022/5/10 18:52
 * 说明: 通用的Y轴
 * =======================================
 */
open class ChartYAxis<T> : BaseAxis<T>() where T : Number, T : Comparable<T> {

    /**
     * 记录绑定y轴的组件
     */
    protected var componentList: ArrayList<BaseComponent<T>> = ArrayList()

    /**
     * 纵轴上tag的数量
     * [tagCount] > 1时有效
     */
    var tagCount = 1

    var tagFormat = "%.2f"

    override fun initAxis() {
        orientation = VERTICAL
    }

    override fun calculateCoordinate(bounds: RectF): Float {
        return bounds.left + axisWidth / 2F + (bounds.width() - axisWidth) * axisSite
    }

    override fun drawAxis(canvas: Canvas, bounds: RectF) {
        if (axisWidth < 0F) {
            return
        }
        axisPaint.run {
            color = axisColor
            strokeWidth = axisWidth
        }
        // 计算纵轴显示的横向位置
        val xCoordinate = calculateCoordinate(bounds)
        canvas.drawLine(xCoordinate, bounds.top, xCoordinate, bounds.bottom, axisPaint)
    }

    override fun getIndexByCoordinate(coordinate: Float?, bounds: RectF): Int? {
        return coordinate?.let {
            dataList.run {
                // 上下阈值校验
                var realCoordinate = max(coordinate, bounds.top)
                realCoordinate = min(realCoordinate, bounds.bottom)
                // 转换屏幕位置为图表中的坐标位置
                var chartCoordinate = bounds.bottom - realCoordinate
                // 根据百分比计算对应的index
                (chartCoordinate / bounds.height() * (size - 1) + 0.5F).toInt()
            }
        }

    }

    override fun getCoordinateByIndex(index: Int, bounds: RectF): Float? {
        return dataList?.run {
            val step = bounds.height() / (size - 1)
            bounds.bottom - step * index
        }
    }

    fun bindComponent(component: BaseComponent<T>?) {
        component?.run {
            if (!componentList.contains(this)) {
                componentList.add(this)
            }
        }
    }

    fun unBindComponent(component: BaseComponent<T>?) {
        component?.run {
            if (componentList.contains(this)) {
                componentList.remove(this)
                notifyDataChange()
            }
        }
    }

    fun clearComponent() {
        componentList.clear()
        axisTag.clearTags()
        notifyDataChange()
    }

    fun notifyDataChange() {
        calculateMaxValue()
        calculateMinValue()
        calculateTag()
    }

    /**
     * 根据最大值，最小值计算tag
     */
    protected open fun calculateTag() {
        axisTag.clearTags()
        if (tagCount > 1) {
            maxValue?.toFloat()?.let { max ->
                minValue?.toFloat()?.let { min ->
                    val step = (max - min) / (tagCount - 1)
                    var start = min
                    for (i in 0 until tagCount) {
                        axisTag.addTag(formatTag(start))
                        start += step
                    }
                }
            }
        }
    }

    protected open fun formatTag(data: Number): String {
        return String.format(tagFormat, data)
    }

    override fun calculateMaxValue() {
        var tempMaxValue: T? = null
        componentList.forEach {
            if (tempMaxValue == null) {
                tempMaxValue = it.maxValue
            } else {
                tempMaxValue?.run {
                    it.maxValue?.let { data ->
                        // maxValue < data 时 返回值 result 为负数
                        val result = this.compareTo(data)
                        if (result < 0) {
                            // 更新 maxValue
                            tempMaxValue = data
                        }
                    }

                }
            }
        }
        this.maxValue = tempMaxValue
    }

    override fun calculateMinValue() {
        var tempMinValue: T? = null
        componentList.forEach {
            if (tempMinValue == null) {
                tempMinValue = it.minValue
            } else {
                tempMinValue?.run {
                    it.minValue?.let { data ->
                        // minValue > data 时 返回值 result 为正数
                        val result = this.compareTo(data)
                        if (result > 0) {
                            // 更新 minValue
                            tempMinValue = data
                        }
                    }

                }
            }
        }
        this.minValue = tempMinValue
    }

}